#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <functional>
#include <sys/wait.h>
#include "protocol.hpp"
#include <cassert>



namespace zxf
{
    enum zxf_err
    {
        USE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR,
        ACCEPT_ERR,
        READ_ERR,
        WRITE_ERR,
        CONNECT_ERR,
        WAAITPID_ERR
    };
}

// 我们要把tcp服务器设计为一个对象

// 默认端口
static const uint16_t default_port = 11111;
// 默认ip
static const std::string default_ip = "0.0.0.0";
// 默认listen 参数
static const int gbacklog = 5;

namespace zxf
{

    // 业务处理可以独立出去,单独的hpp文件
    response_data func(const request_data &req)
    {
        response_data resp;
        // req已经有结构化完成的数据啦，你可以直接使用
        resp._errCode = 0;
        resp._result = 0;

        switch (req._op)
        {
        case '+':
            resp._result = req._x + req._y;
            break;
        case '-':
            resp._result = req._x - req._y;
            break;
        case '*':
            resp._result = req._x * req._y;
            break;
        case '/':
        {
            if (req._y == 0)
                resp._errCode = 1;
            else
                resp._result = req._x / req._y;
        }
        break;
        case '%':
        {
            if (req._y == 0)
                resp._errCode = 1;
            else
                resp._result = req._x % req._y;
        }
        break;
        default:
            resp._errCode = 1;
            break;
        }

        return resp;
    }

    // 协议处理
    void hander(int sock)
    {
        // 服务器接受信息然后 返回
        for (;;)
        {
            // 1.先保证读取到一个完整的request报文(request_str)
            static std::string buf = ""; // 必须未静态

            std::string request_str = "";
            if (!complete_read(sock, request_str, buf))
            {
                std::cout << "complete_read error , exit" << std::endl;
                exit(1);
            }
            // 读取到完整的报文
 

            // 去掉报头
            std::string reuest_data_str = enHeaders(request_str);


            // 反序列化
            request_data req;
            req.reserialize(reuest_data_str);
            response_data resp=resp = func(req);
            

            std::string response_data_str =resp.serialize();


            std::cout << "response_data_str:" << std::endl
                      << response_data_str << std::endl;

            // 添加报头
            std::string response_str = Headers(response_data_str);
            std::cout << "response_str:" << std::endl
                      << response_str << std::endl;

            // 这里发送也是需要保证发送出去完整的报文
            // 先不与保证,以后学习
            send(sock, response_str.c_str(), response_str.size(), 0);
        }

        // 2.去掉协议报头 得到request_data_str

        // 3.对request_data反序列化,得到结构化的request_data

        // 4.给func函数传入request_data 业务处理后 返回一个response_data结构化

        // 5.对response_data序列化,得到response_data_str

        // 6.对response_data_str添加协议报头 得到response报文(response_str)
    }

    class Tcp_server
    {
    public:
        Tcp_server(const int16_t &port = default_port) // 构造函数
            : _port(port), _listensock(-1)
        {
        }
        // 服务器初始化
        void initServer()
        {
            _listensock = socket(AF_INET, SOCK_STREAM, 0);
            if (_listensock == -1)
            {
                std::cout << "socket error , exit" << std::endl;
                exit(1);
            }
            std::cout << "socket success!! " << std::endl;

            struct sockaddr_in local;
            socklen_t len = sizeof(local);
            ////先初始化为0
            memset(&local, 0, len);
            // bzero(&local, len);
            // 二选其一
            local.sin_family = AF_INET;         // 协议家族
            local.sin_port = htons(_port);      // 注意主机字节序转换为网络字节序
            local.sin_addr.s_addr = INADDR_ANY; // 直接绑定任意ip即可
            // local.sin_addr.s_addr = inet_addr(default_ip.c_str());
            int ret = bind(_listensock, (const struct sockaddr *)&local, len);
            if (ret == -1)
            {
                std::cout << "bind error , exit" << std::endl;
                exit(1);
            }
            std::cout << "bind success !!" << std::endl;

            // 设置监听状态 (listen)
            listen(_listensock, gbacklog);
            if (ret == -1)
            {
                exit(1);
            }
            std::cout << "listen success !!" << std::endl;
        }

        // 开始运行服务器
        void start()
        {
            for (;;)
            {
                struct sockaddr_in net;
                socklen_t len = sizeof(net);
                bzero(&net, len);
                int accept_fd = accept(_listensock, (struct sockaddr *)&net, &len);

                if (accept_fd == -1)
                {
                    std::cout << "accept error , exit" << std::endl;
                    continue;
                }
                std::cout << "accept success !! " << std::endl;

                int id = fork();
                if (id == 0)
                {
                    // 子进程
                    if (fork() > 0)
                    {
                        exit(0);
                    }
                    // 孙子进程 --->孤儿进程
                    hander(accept_fd);
                    // 我们让孙子进程去执行对应的程序我们不管进程返回信息
                    exit(0);
                }

                int ret = waitpid(id, nullptr, 0); // 不关心进程退出信息
                if (ret < 0)
                {
                    std::cout << "waitpid error , exit" << std::endl;
                    exit(1);
                }
                std::cout << "waitpid success !!" << std::endl;
            }
        }

    private:
        int16_t _port;   // 服务器绑定的port
        int _listensock; // 监听套接字
    };

} // namespace zxf  end!!
